﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

namespace frp_tool
{

    public delegate void DelReadStdOutput(string result);
    public delegate void DelReadErrOutput(string result);
    public delegate void DelProcessExit();
    public partial class Form1 : Form
    {
        public event DelReadStdOutput ReadStdOutput;
        public event DelReadErrOutput ReadErrOutput;
        public event DelProcessExit ProcessExit;

        private bool process_run;



        public Form1()
        {
            InitializeComponent();
            init();
        }

        private void init()
        {
            //3.将相应函数注册到委托事件中  
            ReadStdOutput += new DelReadStdOutput(ReadStdOutputAction);
            ReadErrOutput += new DelReadErrOutput(ReadErrOutputAction);
            ProcessExit += new DelProcessExit(ProcessExitAction);

            process_run = false;
    
        

           

        }



        private INIConfig config;
        private Process process;

        private void Form1_Load(object sender, EventArgs e)
        {
            MyConsole.setTextBox(consoleRichText);

            if (!File.Exists("frpc.ini"))
            {
                MyConsole.warning("配置文件frpc.ini不存在！");
            }
            string basePath = Application.StartupPath;
            config = new INIConfig(basePath+"/frpc.ini");

            loadConfig();

            //检查frpc 是否存在 https://diannaobos.com/frp/
            if (!File.Exists("./frpc.exe"))
            {
              //  MessageBox.Show(this,"frp客户端不存在！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                MyConsole.error("frp客户端不存在！ 请前往 https://diannaobos.com/frp/ 下载。");
                connectBtn.Enabled = false;
                disconnectAllBtn.Enabled = false;
                disconnectBtn.Enabled = false;
              
            }
            else
            {
                setProcess();
            }
           






        }

        private void loadConfig()
        {
           
            serverAddrText.Text = config.get("common", "server_addr");
            serverPortText.Text = config.get("common", "server_port");
            tokenText.Text = config.get("common", "token");
            localAddrText.Text = config.get("web", "local_ip","localhost");
            localPortText.Text = config.get("web", "local_port", "80");
            remotePortText.Text = config.get("web", "remote_port", "80");

        }

        private void setProcess()
        {
            process = new Process();

            process.StartInfo.UseShellExecute = false;   //是否使用操作系统shell启动 
            process.StartInfo.CreateNoWindow = true;   //是否在新窗口中启动该进程的值 (不显示程序窗口)
            process.StartInfo.RedirectStandardInput = true;  // 接受来自调用程序的输入信息 
            process.StartInfo.RedirectStandardOutput = true;  // 由调用程序获取输出信息
            process.StartInfo.RedirectStandardError = true;  //重定向标准错误输出
            process.StartInfo.FileName = "frpc.exe";
            process.StartInfo.Arguments = "-c frpc.ini";
           // process.StandardInput.AutoFlush = true;

            process.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
            process.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);

         
            process.EnableRaisingEvents = true;                      // 启用Exited事件  
            process.Exited += new EventHandler(Process_Exited);   // 注册进程结束事件  


        }

        private void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null)
            {
                // 4. 异步调用，需要invoke  
                this.Invoke(ReadStdOutput, new object[] { e.Data });
            }
        }

        private void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null)
            {
                this.Invoke(ReadErrOutput, new object[] { e.Data });
            }
        }

        private void ReadStdOutputAction(string result)
        {
            MyConsole.write(result);
        }

        private void ReadErrOutputAction(string result)
        {
            MyConsole.error(result);
        }

        private void Process_Exited(object sender,EventArgs e)
        {
            this.Invoke(ProcessExit);
        }

        private void ProcessExitAction()
        {
            process_run = false;
            connectBtn.Enabled = true;
            process.CancelErrorRead();
            process.CancelOutputRead();
            MyConsole.write("process exit");


        }

        private void connectBtn_Click(object sender, EventArgs e)
        {
            if (process != null&&!process_run)
            {

                start_process();

            }
            else
            {
                MyConsole.warning("process is running");
            }

           
        }

        private void disconnectBtn_Click(object sender, EventArgs e)
        {

            if (process_run&&!process.HasExited)
            {
                process.Kill();
            }

            else
            {
                MyConsole.write("process is not running");
            }
            
        }

        private void disconnectAllBtn_Click(object sender, EventArgs e)
        {
            Process[] processes = Process.GetProcessesByName("frpc");
            foreach (Process instance in processes)
            {
                MyConsole.write(instance.Id.ToString());
                instance.Kill();
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
           
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            WindowState = FormWindowState.Minimized;
        }

        private void start_process()
        {
            write_config();
            process.Start();
            process_run = true;
            connectBtn.Enabled = false;
            process.BeginErrorReadLine();
            process.BeginOutputReadLine();
        }
        private void write_config()
        {
            config.set("common","server_addr",serverAddrText.Text);
            config.set("common", "server_port", serverPortText.Text);
            config.set("common", "token", tokenText.Text);
            config.set("web", "local_ip", localAddrText.Text);
            config.set("web", "local_port", localPortText.Text);
            config.set("web", "remote_port", remotePortText.Text);
        }



        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                WindowState = FormWindowState.Normal;
                ShowInTaskbar = true;
            }
        }



        private void ShowDialogMenuItem_Click(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                WindowState = FormWindowState.Normal;
                ShowInTaskbar = true;
            }
        }

        private void ExitMenuItem_Click(object sender, EventArgs e)
        {
            if (process_run && !process.HasExited)
            {
                process.Kill();
            }
            notifyIcon1.Visible = false;
            Application.Exit();
        }

        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                ShowInTaskbar = false;
            }
        }
    }
}
